import datetime
import os
import sqlite3
import time

import consts


def row_factory(cursor, row):
    d = dict()
    for idx, col in enumerate(cursor.description):
        d[col[0]] = row[idx]
    return d


class Task:
    __base_dir__ = os.path.join(os.path.expanduser('~'), 'sqlite3')

    def __init__(self, name):
        self.name = name
        self.init()

    @property
    def path(self):
        if not os.path.exists(self.__base_dir__):
            os.mkdir(self.__base_dir__)
        return os.path.join(self.__base_dir__, self.name + '.db')

    @property
    def begin(self):
        now = datetime.datetime.now()
        now = datetime.datetime(year=now.year, month=now.month, day=now.day)
        return now.timestamp()

    def insert(self, timestamp, signal_hex_id, market, symbol, direction, side, quantity, order_id, order_status, error_id):
        with sqlite3.connect(self.path) as conn:
            conn.execute(
                'INSERT INTO task (timestamp, signal_hex_id, market, symbol, direction, side, quantity, deal_quantity, state, order_id, order_status, error_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
                (timestamp, signal_hex_id, market, symbol, direction, side, quantity, 0, 0, order_id, order_status, error_id, time.time(), time.time())
            )
            conn.commit()

    def update(self, primary_key_id, deal_quantity, order_id, order_status, error_id, state):
        with sqlite3.connect(self.path) as conn:
            conn.execute(
                'UPDATE task SET deal_quantity = ?, order_id = ?, order_status = ?, error_id = ?, state = ?, updated_at = ? WHERE id = ?',
                (deal_quantity, order_id, order_status, error_id, state, time.time(), primary_key_id)
            )
            conn.commit()

    def count(self, signal_hex_id):
        with sqlite3.connect(self.path) as conn:
            cursor = conn.execute(
                'SELECT * FROM task WHERE signal_hex_id = ?',
                (signal_hex_id,)
            )
            result = cursor.fetchall()
            return len(result)

    def slack(self):
        with sqlite3.connect(self.path) as conn:
            conn.row_factory = row_factory
            cursor = conn.execute(
                'SELECT * FROM task WHERE state = ? AND timestamp > ? AND order_status IN (?, ?)',
                (1, self.begin, consts.XTP_ORDER_STATUS_TYPE.XTP_ORDER_STATUS_INIT.value, consts.XTP_ORDER_STATUS_TYPE.XTP_ORDER_STATUS_NOTRADEQUEUEING.value)
            )
            return cursor.fetchall()

    def again(self):
        with sqlite3.connect(self.path) as conn:
            conn.row_factory = row_factory
            cursor = conn.execute(
                'SELECT * FROM task WHERE state = ? AND timestamp > ? AND order_status IN (?, ?)',
                (1, self.begin, consts.XTP_ORDER_STATUS_TYPE.XTP_ORDER_STATUS_PARTTRADEDNOTQUEUEING.value, consts.XTP_ORDER_STATUS_TYPE.XTP_ORDER_STATUS_CANCELED.value)
            )
            return cursor.fetchall()

    def query(self):
        with sqlite3.connect(self.path) as conn:
            conn.row_factory = row_factory
            cursor = conn.execute(
                'SELECT * FROM task WHERE state = ? AND timestamp > ? AND timestamp < ? ',
                (0, self.begin, time.time())
            )
            return cursor.fetchall()

    def fetch(self, primary_key_id):
        with sqlite3.connect(self.path) as conn:
            conn.row_factory = row_factory
            cursor = conn.execute(
                'SELECT * FROM task WHERE id = ?',
                (primary_key_id,)
            )
            return cursor.fetchone()

    def init(self):
        with sqlite3.connect(self.path) as conn:
            conn.execute(
                '''
                CREATE TABLE IF NOT EXISTS task (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    timestamp INTEGER NOT NULL,
                    signal_hex_id TEXT NOT NULL,
                    market TEXT NOT NULL,
                    symbol TEXT NOT NULL,
                    direction TEXT NOT NULL,
                    side TEXT NOT NULL,
                    quantity INTEGER NOT NULL,
                    deal_quantity INTEGER NOT NULL,
                    state INTEGER NOT NULL,
                    order_id INTEGER NOT NULL,
                    order_status INTEGER NOT NULL,
                    error_id INTEGER NOT NULL,
                    created_at INTEGER NOT NULL,
                    updated_at INTEGER NOT NULL
                )   
                '''
            )
